#ifndef CSGNODE_H
#define CSGNODE_H

#ifndef NULL
#define NULL 0
#endif

#include "expression/expression.hpp"
#include "expression/variable.hpp"
#include "tree/treenode.h"
#include "tree/tree.h"
#include "tree/startestbox.h"
#include "../constants.h"

typedef ::expression::Expression Expression;
typedef ::expression::Variable Variable;
typedef ::numeric::interval Interval;
const int DIM_SPACE = 3;
const double transparency = 0.5;

extern double boxColor[BOX_POS_END][4];
void drawBox(TreeNode<StarTestBox> *node);
void drawBoxBound(TreeNode<StarTestBox> *node);

class CSGNode : public TreeNode<int>
{
public:
    CSGNode(int a, TreeNode<int> *parent = NULL);
    virtual ~CSGNode();

    virtual void setRotation(double _rot);
    virtual void setTranslation(double *tr);
    virtual void setTranslation(double x, double y = 0);
    virtual void setScale(double *s);
    virtual void setScale(double x, double y = 1);

    virtual void initial(StarTestBox &box, int dim = 2);

    virtual double eval(double x, double y, double z){return 1.;}

    // draw
    virtual void drawBoundingBox();
    virtual void drawControlPolygon(bool fill = false);
    virtual void drawNaively(bool grid = false);
    virtual void drawCasteljau(int level = 5);
    virtual void drawDomain(bool grid);
    virtual void drawBoxDomainTest(bool grid);
    virtual void drawContour();

    // test
    virtual bool emptyTest(StarTestBox *box){return box->isOuter();}
    virtual bool starTest(StarTestBox *box, double *pt){return box->isStar();}
    virtual bool complementStarTest(StarTestBox *box, double *pt){return box->isStar();}
    virtual bool ptInSet(double *pt){return false;}

protected:
    void emptyTest(TreeNode<StarTestBox> * node);
    static bool subdivideTestNode(TreeNode<StarTestBox> * node, bool critical, double threshold, int n = 0, double *r = 0);

    Tree<StarTestBox> * emptyTestTree;
    StarTestBox viewBox;
    std::vector<StarTestBox*> innerBoxes;
    std::vector<StarTestBox*> bdBoxes;
};

#endif // CSGNODE_H
